unit uTextEditorMainForm;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Actions,
  FMX.ActnList, FMX.Menus, FMX.Controls.Presentation, FMX.StdCtrls,
  FMX.Memo.Types, FMX.ScrollBox, FMX.Memo;

type
  TTextEditorForm = class(TForm)
    ActionList: TActionList;
    MainMenu: TMainMenu;
    StatusBar: TStatusBar;
    Editor: TMemo;
    OpenDialog: TOpenDialog;
    SaveDialog: TSaveDialog;
    NewAction: TAction;
    OpenAction: TAction;
    SaveAction: TAction;
    SaveAsAction: TAction;
    ExitAction: TAction;
    CutAction: TAction;
    CopyAction: TAction;
    PasteAction: TAction;
    SelectAllAction: TAction;
    UndoAction: TAction;
    DeleteAction: TAction;
    WordWrapAction: TAction;
    FileMenu: TMenuItem;
    EditMenu: TMenuItem;
    FormatMenu: TMenuItem;
    MenuItem4: TMenuItem;
    MenuItem5: TMenuItem;
    MenuItem6: TMenuItem;
    MenuItem7: TMenuItem;
    MenuItem8: TMenuItem;
    MenuItem9: TMenuItem;
    MenuItem10: TMenuItem;
    MenuItem11: TMenuItem;
    MenuItem12: TMenuItem;
    MenuItem13: TMenuItem;
    MenuItem14: TMenuItem;
    MenuItem15: TMenuItem;
    LineNum: TLabel;
    ColumnNum: TLabel;
    LineCount: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure EditorKeyDown(Sender: TObject; var Key: Word;
      var KeyChar: WideChar; Shift: TShiftState);
    procedure EditorKeyUp(Sender: TObject; var Key: Word; var KeyChar: WideChar;
      Shift: TShiftState);
    procedure NewActionExecute(Sender: TObject);
    procedure OpenActionExecute(Sender: TObject);
    procedure SaveActionExecute(Sender: TObject);
    procedure SaveAsActionExecute(Sender: TObject);
    procedure ExitActionExecute(Sender: TObject);
    procedure CutActionExecute(Sender: TObject);
    procedure CopyActionExecute(Sender: TObject);
    procedure PasteActionExecute(Sender: TObject);
    procedure SelectAllActionExecute(Sender: TObject);
    procedure UndoActionExecute(Sender: TObject);
    procedure DeleteActionExecute(Sender: TObject);
    procedure WordWrapActionExecute(Sender: TObject);
    procedure EditorClick(Sender: TObject);
  private
    { Private declarations }
    CurrentFile: string;
    procedure UpdateStatusBar;
  public
    { Public declarations }
  end;

var
  TextEditorForm: TTextEditorForm;

implementation

{$R *.fmx}

uses
  FMX.DialogService.Sync;

{ TTextEditorForm }

procedure TTextEditorForm.CopyActionExecute(Sender: TObject);
begin
  Editor.CopyToClipboard;
end;

procedure TTextEditorForm.CutActionExecute(Sender: TObject);
begin
  Editor.CutToClipboard;
  UpdateStatusBar;
end;

procedure TTextEditorForm.DeleteActionExecute(Sender: TObject);
begin
  if Editor.SelLength > 0 then
    Editor.DeleteSelection
  else
    Editor.DeleteFrom(Editor.CaretPosition, 1, [TDeleteOption.MoveCaret]);
  UpdateStatusBar;
end;

procedure TTextEditorForm.EditorClick(Sender: TObject);
begin
  UpdateStatusBar;
end;

procedure TTextEditorForm.EditorKeyDown(Sender: TObject; var Key: Word;
  var KeyChar: WideChar; Shift: TShiftState);
begin
  UpdateStatusBar;
end;

procedure TTextEditorForm.EditorKeyUp(Sender: TObject; var Key: Word;
  var KeyChar: WideChar; Shift: TShiftState);
begin
  UpdateStatusBar;
end;

procedure TTextEditorForm.ExitActionExecute(Sender: TObject);
begin
  Application.Terminate;
end;

procedure TTextEditorForm.FormCreate(Sender: TObject);
begin
  Editor.Lines.Add('');
  UpdateStatusBar;
end;

procedure TTextEditorForm.NewActionExecute(Sender: TObject);
var
  UserResponse: Integer;
begin
  // Ask for confirmation if the memo is not empty.
  if not Editor.Text.IsEmpty then
  begin
    UserResponse := TDialogServiceSync.MessageDialog(
      'This will clear the current document. Do you want to continue?',
      TMsgDlgType.mtInformation, mbYesNo, TMsgDlgBtn.mbYes, 0);
    if UserResponse = mrYes then
    begin
      Editor.Text := '';
      Editor.Lines.Add(''); // Initialize the memo line count to "1".
      UpdateStatusBar;
      CurrentFile := ''; // New files have no file name until saved.
    end;
  end;
end;

procedure TTextEditorForm.OpenActionExecute(Sender: TObject);
var
  FileName: String;
begin
  if OpenDialog.Execute then
  begin
    FileName := OpenDialog.FileName;
    if FileExists(FileName) then
    begin
      Editor.Lines.LoadFromFile(FileName);
      CurrentFile := FileName;
      Caption := 'Text Editor - ' + ExtractFileName(FileName);
    end;
  end;
end;

procedure TTextEditorForm.PasteActionExecute(Sender: TObject);
begin
  Editor.PasteFromClipboard;
  UpdateStatusBar;
end;

procedure TTextEditorForm.SaveActionExecute(Sender: TObject);
begin
  if CurrentFile = '' then
    SaveAsAction.Execute()
  else
    Editor.Lines.SaveToFile(CurrentFile);
end;

procedure TTextEditorForm.SaveAsActionExecute(Sender: TObject);
var
  FileName: String;
  UserResponse: TModalResult;
begin
  if SaveDialog.Execute then
  begin
    FileName := SaveDialog.FileName;
    if FileExists(FileName) then
    begin
      UserResponse := TDialogServiceSync.MessageDialog(
        'File already exists. Do you want to overwrite?',
        TMsgDlgType.mtInformation, mbYesNo, TMsgDlgBtn.mbYes, 0);
      if UserResponse = mrNo then
        Exit;
    end;
    Editor.Lines.SaveToFile(FileName);
    CurrentFile := FileName;
    Caption := 'Text Editor - ' + ExtractFileName(FileName);
  end;
end;

procedure TTextEditorForm.SelectAllActionExecute(Sender: TObject);
begin
  Editor.SelectAll;
  UpdateStatusBar;
end;

procedure TTextEditorForm.UndoActionExecute(Sender: TObject);
begin
  Editor.UnDo;
  UpdateStatusBar;
end;

procedure TTextEditorForm.UpdateStatusBar;
begin
  LineNum.Text := 'L: ' + (Editor.CaretPosition.Line + 1).ToString;
  ColumnNum.Text := 'C: ' + (Editor.CaretPosition.Pos + 1).ToString;
  LineCount.Text := 'Lines: ' + Editor.Lines.Count.ToString;
end;

procedure TTextEditorForm.WordWrapActionExecute(Sender: TObject);
begin
  Editor.WordWrap := not Editor.WordWrap;
  WordWrapAction.Checked := Editor.WordWrap;
  UpdateStatusBar;
end;

end.
